(**********************************************************************

    :Program.    Lists.def
    :Contents.   Generic data type: List
    :Author.     Nicolas Benezan [bne]
    :Address.    Postwiesenstr. 2, D7000 Stuttgart 60
    :Phone.      711/333679
    :Copyright.  Public Domain
    :Language.   Modula-2
    :Translator. M2Amiga AMSoft 3.11
    :Imports.    TaskMemory [bne]
    :History.    V1.0 [mif] 13.Sep.1988
    :History.    V1.1 [bne] 8.Feb.1989 (V1.0 modified)
    :History.    V2.0d [bne] 4.Mar.1989 (complete new version)
    :History.    V2.1a [bne] 22.Mar.1989 (Bug in CreateList() fixed)

**********************************************************************)

DEFINITION MODULE Lists;

FROM SYSTEM     IMPORT BYTE, ADDRESS;
FROM Exec       IMPORT MinNode;

TYPE    List;
        EntryPtr=POINTER TO Entry;
        (* EntryPtr and Entry should be considered as opaque.
           Do not access them directly unless you want to expand
           the features of Lists *)
        Entry=RECORD
          node:MinNode;
          dataSize:CARDINAL;
          dataPtr:ADDRESS;
        END;

VAR     ListsAllocProc:PROCEDURE(VAR ADDRESS,LONGINT);
        ListsDeallocProc:PROCEDURE(VAR ADDRESS);
(* defaults are TaskMemory.Allocate and TaskMemory.Deallocate *)

PROCEDURE CreateList(VAR list:List):BOOLEAN;
(*:Semantic.    Creates an initializes a new list for further use
  :Note.        Never use a list before having CreateList()ed it !!!
*)

PROCEDURE AppendEntry(list:List;
                      DataSize:CARDINAL;
                      DataAddr:ADDRESS);
(*:Semantic.    Appends data of given address and size to list
  :Note.        Data will be actually a part of list, so don't reuse it
*)

PROCEDURE AppendEntryC(list:List;
                   VAR Data:ARRAY OF BYTE);
(*:Semantic.    Allocates a new entry, copies data and appends it
  :Output.      Data remains unchanged (VAR for efficiency)
*)

PROCEDURE RemoveEntry(list:List;
                  VAR entry:EntryPtr);
(*:Semantic.    Removes an entry from list, does not delete its data
  :Input.       Entry: entry to be removed
  :Output.      Entry: always NIL
  :Note.        complement of InsertEntry() or AppendEntry()
*)

PROCEDURE DeleteEntry(list:List;
                      entry:EntryPtr);
(*:Semantic.    Removes an entry and deallocates its data
  :Input.       Entry: entry to be removed
  :Note.        complement of InsertEntryC() or AppendEntryC()
*)

PROCEDURE DeleteList(VAR list:List);
(*:Semantic.    DeleteEntry()s all entries and discards the list
*)

PROCEDURE InsertEntry(list:List;
                      Position:EntryPtr;
                      DataSize:CARDINAL;
                      DataAddr:ADDRESS);
(*:Semantic.    Inserts an entry BEFORE a given position
  :Semantic.    Data is not copied.
*)

PROCEDURE InsertEntryC(list:List;
                       Position:EntryPtr;
                   VAR Data:ARRAY OF BYTE);
(*:Semantic.    allocates a new entry, copies Data into it
  :Semantic.    and InsertEntry()s it
  :Output.      Data remains unchanged (VAR for efficiency)
*)

PROCEDURE ListOk(list:List):BOOLEAN;
(*:Semantic.    returns wether previous actions on list have
  :Semantic.    been succesful.
  :Result.      FALSE, if there have been one or more errors since
  :Result.      the last call to ListOk(), otherwise TRUE
  :Note.        Error conditions are:
  :Note.         - No free memory while appending
  :Note.         - No free memory while inserting
  :Note.         - Remove an undefined (EntryPtr=NIL) entry
  :Note.         - Read an undefined (EntryPtr=NIL) entry
  :Note.         - Replace an undefined (EntryPtr=NIL) entry
  :Note.         - Try to locate a not existing entry
  :Note.           (Position>=NumEntries)
  :Note.         - FirstEntry() of an empty list
  :Note.         - LastEntry() of an empty list
  :Note.        WARNING: not every possible error can be fixed.
  :Note.        Operations on lists which are not properly initialised,
  :Note.        for example, may crash the system!
*)

PROCEDURE EntriesInList(list:List):CARDINAL;
(*:Semantic.    returns how many entries are currently in the list
  :Note.        keep in mind that the result is meaningless for
  :Note.        shared lists unless executed Forbid()den
*)

PROCEDURE ReadEntry(list:List;
                    entry:EntryPtr;
                VAR DataSize:CARDINAL;
                VAR DataAddr:ADDRESS);
(*:Semantic.    returns the address and size of the data
*)

PROCEDURE ReadEntryC(list:List;
                     entry:EntryPtr;
                 VAR Data:ARRAY OF BYTE);
(*:Semantic.    provides a copy of the data
*)

PROCEDURE ReplaceEntry(list:List;
                       entry:EntryPtr;
                       DataSize:CARDINAL;
                       DataAddr:ADDRESS);
(*:Semantic.    replaces the old data in the specified entry with the
  :Semantic.    new one. Neither is any data moved or copied, nor is
  :Semantic.    any allocation/deallocation done.
  :Note.        If you don't have a pointer to the old data, it will be 
  :Note.        garbage!
*)

PROCEDURE ReplaceEntryC(list:List;
                        entry:EntryPtr;
                    VAR Data:ARRAY OF BYTE);
(*:Semantic.    copies Data into the data field of an entry
  :Semantic.    Data must have same or smaller size than that field
  :Note.        (size of the entry will not change if Data is smaller)
*)

PROCEDURE LocateEntryAbs(list:List;
                         Position:CARDINAL):EntryPtr;
(*:Semantic.    returns a pointer to the entry referenced by its
  :Semantic.    number (starting with 0 from the beginning)
  :Result.      Pointer to the referenced entry
  :Result.      undefined, if Position>=NumEntries(list)
*)

PROCEDURE LocateEntryRel(list:List;
                     VAR entry:EntryPtr;
                         Offset:INTEGER):BOOLEAN;
(*:Semantic.    positions forward (psitive Offset) or backward (negative)
  :Result.      FALSE, if positioned after the last or before the 
  :Result.      first entry
*)

PROCEDURE Successor(VAR entry:EntryPtr):BOOLEAN;
(*:Input.       entry: entry of which you want to know the successor
  :Result.      TRUE, if entry (Input) has a successor, FALSE, if not
  :Output.      entry: succesor if result is TRUE, otherwise undefined
*)

PROCEDURE Predecessor(VAR entry:EntryPtr):BOOLEAN;
(*:Input.       entry: entry of which you want to know the predecessor
  :Result.      TRUE, if entry (Input) has a predecessor, FALSE, if not
  :Output.      entry: predecessor if result is TRUE, otherwise undefined
*)

PROCEDURE FirstEntry(list:List):EntryPtr;
(*:Result.      pointer to the first entry, undefined if list is empty
*)
PROCEDURE LastEntry(list:List):EntryPtr;
(*:Result.      pointer to the last entry, undefined if list is empty
*)

END Lists.

